package module.bank.impl;

import common.model.Entity.bankEntity.Account;
import common.model.Entity.bankEntity.Transaction;
import dao.BankDao.AccountDao;
import dao.BankDao.TransactionDao;
import dao.impl.BankDaoImpl.AccountDaoImpl;
import dao.impl.BankDaoImpl.TransactionDaoImpl;
import module.bank.BankAccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import network.protocol.Response;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * {@code BankAccountServiceImpl} 是 {@link BankAccountService} 的实现类，
 * 提供银行账户的业务逻辑服务。
 * <p>
 * 功能包括：
 * <ul>
 *     <li>账户增删改查</li>
 *     <li>充值、取款、转账</li>
 *     <li>交易记录查询</li>
 * </ul>
 * <p>
 * 使用单例模式，可通过 {@link #getInstance()} 获取唯一实例。
 * </p>
 */
public class BankAccountServiceImpl implements BankAccountService {

    /** 日志记录器 */
    private static final Logger logger = LoggerFactory.getLogger(BankAccountServiceImpl.class);

    /** 账户 DAO */
    private final AccountDao accountDao;

    /** 交易 DAO */
    private final TransactionDao transactionDao;

    /** 单例实例 */
    private static final BankAccountServiceImpl INSTANCE = new BankAccountServiceImpl();

    /**
     * 获取单例实例。
     *
     * @return {@link BankAccountServiceImpl} 实例
     */
    public static BankAccountServiceImpl getInstance() {
        return INSTANCE;
    }

    /**
     * 构造函数，初始化 DAO 实现类。
     */
    public BankAccountServiceImpl() {
        this.accountDao = new AccountDaoImpl();
        this.transactionDao = new TransactionDaoImpl();
    }

    /**
     * 根据用户 ID 查询账户列表。
     *
     * @param userId 用户 ID
     * @return 包含账户列表的响应
     */
    @Override
    public Response<List<Account>> getAccountsByUserId(Long userId) {
        try {
            List<Account> accounts = accountDao.findAccountsByUserId(userId);
            return Response.success(accounts);
        } catch (Exception e) {
            logger.error("获取用户账户列表失败: userId={}", userId, e);
            return Response.error("获取用户账户列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据账户 ID 查询账户信息。
     *
     * @param accountId 账户 ID
     * @return 包含账户的响应，可能为空
     */
    @Override
    public Response<Optional<Account>> getAccountById(Long accountId) {
        try {
            Account account = accountDao.findAccountById(accountId);
            return Response.success(Optional.ofNullable(account));
        } catch (Exception e) {
            logger.error("获取账户信息失败: accountId={}", accountId, e);
            return Response.error("获取账户信息失败: " + e.getMessage());
        }
    }

    /**
     * 为指定账户充值。
     *
     * @param accountId 账户 ID
     * @param amount    充值金额
     * @return 是否成功的响应
     */
    @Override
    public Response<Boolean> recharge(Long accountId, BigDecimal amount) {
        try {
            // 获取账户
            Account account = accountDao.findAccountById(accountId);
            if (account == null) {
                logger.warn("充值失败: 账户不存在, accountId={}", accountId);
                return Response.error("账户不存在");
            }

            if (account.getStatus() != 1) {
                logger.warn("充值失败: 账户状态异常, accountId={}, status={}", accountId, account.getStatus());
                return Response.error("账户状态异常，无法进行充值操作");
            }

            // 检查充值金额是否超过单次最大存款限制
            if (account.getLimit() != null && amount.compareTo(account.getLimit()) > 0) {
                // 记录失败的交易
                Transaction transaction = createTransaction(
                        account.getUserId(),
                        accountId,
                        amount,
                        0, // 存款
                        "充值失败：超过单次最大充值限额 " + account.getLimit(),
                        0 // 失败
                );
                transactionDao.insertTransaction(transaction);

                logger.warn("充值失败: 超过单次最大充值限额, accountId={}, amount={}, limit={}",
                        accountId, amount, account.getLimit());
                return Response.error("超过单次最大充值限额 " + account.getLimit());
            }

            // 更新余额
            BigDecimal newBalance = account.getBalance().add(amount);
            boolean updateSuccess = accountDao.updateBalance(accountId, newBalance);

            if (updateSuccess) {
                // 记录交易
                Transaction transaction = createTransaction(
                        account.getUserId(),
                        accountId,
                        amount,
                        0, // 存款
                        "充值成功",
                        1 // 成功
                );
                transactionDao.insertTransaction(transaction);

                logger.info("充值成功: accountId={}, amount={}, newBalance={}",
                        accountId, amount, newBalance);
                return Response.success(true);
            } else {
                // 记录失败的交易（数据库更新失败）
                Transaction transaction = createTransaction(
                        account.getUserId(),
                        accountId,
                        amount,
                        0, // 存款
                        "充值失败：系统错误",
                        0 // 失败
                );
                transactionDao.insertTransaction(transaction);

                logger.error("充值失败: 数据库更新失败, accountId={}, amount={}", accountId, amount);
                return Response.error("充值失败：系统错误");
            }
        } catch (Exception e) {
            logger.error("充值操作异常: accountId={}, amount={}", accountId, amount, e);
            return Response.error("充值操作异常: " + e.getMessage());
        }
    }

    /**
     * 创建交易对象（内部辅助方法）。
     *
     * @param userId          用户 ID
     * @param accountId       账户 ID
     * @param amount          金额
     * @param transactionType 交易类型（0:存款, 1:消费）
     * @param description     描述
     * @param status          状态（0:失败, 1:成功）
     * @return 交易对象
     */
    private Transaction createTransaction(Long userId, Long accountId, BigDecimal amount,
                                          int transactionType, String description, int status) {
        Transaction transaction = new Transaction();
        transaction.setUserId(userId);
        transaction.setAccountId(accountId);
        transaction.setAmount(amount);
        transaction.setTransactionType(transactionType);
        transaction.setDescription(description);
        transaction.setStatus(status);
        transaction.setCreatedAt(LocalDateTime.now());
        return transaction;
    }

    /**
     * 从账户取款。
     *
     * @param accountId 账户 ID
     * @param amount    取款金额
     * @return 是否成功的响应
     */
    @Override
    public Response<Boolean> withdraw(Long accountId, BigDecimal amount) {
        try {
            Account account = accountDao.findAccountById(accountId);
            if (account == null) {
                logger.warn("取款失败: 账户不存在, accountId={}", accountId);
                return Response.error("账户不存在");
            }

            if (account.getStatus() != 1) {
                logger.warn("取款失败: 账户状态异常, accountId={}, status={}", accountId, account.getStatus());
                return Response.error("账户状态异常，无法进行取款操作");
            }

            if (account.getBalance().compareTo(amount) < 0) {
                // 记录失败交易
                Transaction tx = createTransaction(account.getUserId(), accountId, amount.negate(),
                        1, "取款失败：余额不足", 0);
                transactionDao.insertTransaction(tx);
                logger.warn("取款失败: 余额不足, accountId={}, balance={}, amount={}",
                        accountId, account.getBalance(), amount);
                return Response.error("余额不足");
            }

            BigDecimal newBalance = account.getBalance().subtract(amount);
            boolean updateSuccess = accountDao.updateBalance(accountId, newBalance);

            if (updateSuccess) {
                Transaction tx = createTransaction(account.getUserId(), accountId, amount.negate(),
                        1, "取款成功", 1);
                transactionDao.insertTransaction(tx);
                logger.info("取款成功: accountId={}, amount={}, newBalance={}",
                        accountId, amount, newBalance);
                return Response.success(true);
            } else {
                Transaction tx = createTransaction(account.getUserId(), accountId, amount.negate(),
                        1, "取款失败：系统错误", 0);
                transactionDao.insertTransaction(tx);
                logger.error("取款失败: 数据库更新失败, accountId={}, amount={}", accountId, amount);
                return Response.error("取款失败：系统错误");
            }
        } catch (Exception e) {
            logger.error("取款操作异常: accountId={}, amount={}", accountId, amount, e);
            return Response.error("取款操作异常: " + e.getMessage());
        }
    }

    /**
     * 修改账户名称。
     *
     * @param accountId 账户 ID
     * @param newName   新名称
     * @return 修改后的账户
     */
    @Override
    public Response<Account> updateAccountName(Long accountId, String newName) {
        try {
            Account account = accountDao.findAccountById(accountId);
            if (account == null) {
                return Response.error("账户不存在");
            }

            account.setAccountName(newName);
            boolean success = accountDao.updateAccountName(accountId, newName);

            if (success) {
                logger.info("修改账户名成功: accountId={}, newName={}", accountId, newName);
                return Response.success(account);
            } else {
                logger.error("修改账户名失败: accountId={}, newName={}", accountId, newName);
                return Response.error("修改账户名失败");
            }
        } catch (Exception e) {
            logger.error("修改账户名异常: accountId={}, newName={}", accountId, newName, e);
            return Response.error("修改账户名异常: " + e.getMessage());
        }
    }

    /**
     * 删除账户。
     *
     * @param accountId 账户 ID
     * @return 是否删除成功
     */
    @Override
    public Response<Boolean> deleteAccount(Long accountId) {
        try {
            Account account = accountDao.findAccountById(accountId);
            if (account == null) {
                return Response.error("账户不存在");
            }

            // ⚠️ 推荐逻辑删除（is_deleted = 1）
            boolean success = accountDao.deleteAccount(accountId);

            if (success) {
                logger.info("删除账户成功: accountId={}", accountId);
                return Response.success(true);
            } else {
                logger.error("删除账户失败: accountId={}", accountId);
                return Response.error("删除账户失败");
            }
        } catch (Exception e) {
            logger.error("删除账户异常: accountId={}", accountId, e);
            return Response.error("删除账户异常: " + e.getMessage());
        }
    }

    /**
     * 执行账户间转账。
     *
     * @param fromAccountId 转出账户 ID
     * @param toAccountId   转入账户 ID
     * @param amount        转账金额
     * @param description   描述
     * @return 是否成功的响应
     */
    @Override
    public Response<Boolean> transfer(Long fromAccountId, Long toAccountId, BigDecimal amount, String description) {
        try {
            Account from = accountDao.findAccountById(fromAccountId);
            Account to = accountDao.findAccountById(toAccountId);

            if (from == null || to == null) {
                logger.warn("转账失败: 账户不存在, from={}, to={}", fromAccountId, toAccountId);
                return Response.error("转出或转入账户不存在");
            }

            if (from.getStatus() != 1 || to.getStatus() != 1) {
                logger.warn("转账失败: 账户状态异常, fromStatus={}, toStatus={}", from.getStatus(), to.getStatus());
                return Response.error("账户状态异常，无法进行转账");
            }

            if (from.getBalance().compareTo(amount) < 0) {
                Transaction tx = createTransaction(from.getUserId(), fromAccountId, amount.negate(),
                        1, "转账失败：余额不足", 0);
                transactionDao.insertTransaction(tx);
                return Response.error("余额不足");
            }

            // 扣钱
            BigDecimal newFromBalance = from.getBalance().subtract(amount);
            boolean fromUpdate = accountDao.updateBalance(fromAccountId, newFromBalance);

            // 加钱
            BigDecimal newToBalance = to.getBalance().add(amount);
            boolean toUpdate = accountDao.updateBalance(toAccountId, newToBalance);

            if (fromUpdate && toUpdate) {
                // 记录两笔交易
                Transaction outTx = createTransaction(from.getUserId(), fromAccountId, amount.negate(),
                        1, "转账支出：" + description, 1);
                transactionDao.insertTransaction(outTx);

                Transaction inTx = createTransaction(to.getUserId(), toAccountId, amount,
                        0, "转账收入：" + description, 1);
                transactionDao.insertTransaction(inTx);

                logger.info("转账成功: from={}, to={}, amount={}", fromAccountId, toAccountId, amount);
                return Response.success(true);
            } else {
                logger.error("转账失败: 数据库更新失败, from={}, to={}", fromAccountId, toAccountId);
                return Response.error("转账失败：系统错误");
            }
        } catch (Exception e) {
            logger.error("转账操作异常: from={}, to={}, amount={}", fromAccountId, toAccountId, amount, e);
            return Response.error("转账操作异常: " + e.getMessage());
        }
    }

    /**
     * 查询交易记录。
     *
     * @param accountId       账户 ID
     * @param startDate       起始时间，可选
     * @param endDate         截止时间，可选
     * @param transactionType 交易类型（0:存款, 1:消费），可选
     * @return 包含交易列表的响应
     */
    @Override
    public Response<List<Transaction>> getTransactionHistory(Long accountId, LocalDateTime startDate, LocalDateTime endDate, Integer transactionType) {
        try {
            List<Transaction> transactions = transactionDao.findTransactionsByAccountId(accountId, startDate, endDate, transactionType);
            return Response.success(transactions);
        } catch (Exception e) {
            logger.error("获取交易记录失败: accountId={}", accountId, e);
            return Response.error("获取交易记录失败: " + e.getMessage());
        }
    }

    /**
     * 创建新账户。
     *
     * @param userId      用户 ID
     * @param accountName 账户名
     * @return 新账户对象
     */
    @Override
    public Response<Account> createAccount(Long userId, String accountName) {
        try {
            Account account = new Account();
            account.setUserId(userId);
            account.setAccountName(accountName);
            account.setBalance(BigDecimal.ZERO); // 初始余额为0

            // 设置默认单次最大存款限额
            account.setLimit(new BigDecimal("50000.00"));

            account.setStatus(1); // 默认正常
            account.setCreatedAt(LocalDateTime.now());

            boolean success = accountDao.save(account);
            if (success) {
                return Response.success(account);
            } else {
                return Response.error("保存账户失败");
            }
        } catch (Exception e) {
            logger.error("创建账户异常: userId={}", userId, e);
            return Response.error("创建账户异常: " + e.getMessage());
        }
    }
}
